home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65c+IDA-1.4.4.1 / src / RCS / queue.c,v < prev    next >
Encoding:
Text File  |  1991-06-25  |  47.0 KB  |  2,405 lines

  1. head    5.30;
  2. branch    5.30.0;
  3. access;
  4. symbols
  5.     RELEASE:5.30.0.28
  6.     BETA:5.30.0.26
  7.     UICSO:5.30.0
  8.     VANILLA:5.30;
  9. locks; strict;
  10. comment    @ * @;
  11.  
  12.  
  13. 5.30
  14. date    90.06.20.08.36.13;    author paul;    state Exp;
  15. branches
  16.     5.30.0.1;
  17. next    ;
  18.  
  19. 5.30.0.1
  20. date    90.06.20.09.43.38;    author paul;    state Exp;
  21. branches;
  22. next    5.30.0.2;
  23.  
  24. 5.30.0.2
  25. date    90.06.21.13.47.18;    author paul;    state Exp;
  26. branches;
  27. next    5.30.0.3;
  28.  
  29. 5.30.0.3
  30. date    90.06.25.09.21.02;    author paul;    state Exp;
  31. branches;
  32. next    5.30.0.4;
  33.  
  34. 5.30.0.4
  35. date    90.07.09.10.17.12;    author paul;    state Exp;
  36. branches;
  37. next    5.30.0.5;
  38.  
  39. 5.30.0.5
  40. date    90.10.13.18.57.10;    author paul;    state Exp;
  41. branches;
  42. next    5.30.0.6;
  43.  
  44. 5.30.0.6
  45. date    90.11.02.00.32.16;    author paul;    state Exp;
  46. branches;
  47. next    5.30.0.7;
  48.  
  49. 5.30.0.7
  50. date    90.11.13.15.20.44;    author paul;    state Exp;
  51. branches;
  52. next    5.30.0.8;
  53.  
  54. 5.30.0.8
  55. date    90.11.15.19.47.10;    author paul;    state Exp;
  56. branches;
  57. next    5.30.0.9;
  58.  
  59. 5.30.0.9
  60. date    90.11.24.16.33.54;    author paul;    state Exp;
  61. branches;
  62. next    5.30.0.10;
  63.  
  64. 5.30.0.10
  65. date    90.11.28.16.26.35;    author paul;    state Exp;
  66. branches;
  67. next    5.30.0.11;
  68.  
  69. 5.30.0.11
  70. date    90.12.11.15.20.41;    author paul;    state Exp;
  71. branches;
  72. next    5.30.0.12;
  73.  
  74. 5.30.0.12
  75. date    91.01.19.19.26.02;    author paul;    state Exp;
  76. branches;
  77. next    5.30.0.13;
  78.  
  79. 5.30.0.13
  80. date    91.02.01.04.49.26;    author paul;    state Exp;
  81. branches;
  82. next    5.30.0.14;
  83.  
  84. 5.30.0.14
  85. date    91.02.17.04.55.44;    author paul;    state Exp;
  86. branches;
  87. next    5.30.0.15;
  88.  
  89. 5.30.0.15
  90. date    91.03.05.21.13.17;    author paul;    state Exp;
  91. branches;
  92. next    5.30.0.16;
  93.  
  94. 5.30.0.16
  95. date    91.03.05.21.14.06;    author paul;    state Exp;
  96. branches;
  97. next    5.30.0.17;
  98.  
  99. 5.30.0.17
  100. date    91.03.18.00.41.45;    author paul;    state Exp;
  101. branches;
  102. next    5.30.0.18;
  103.  
  104. 5.30.0.18
  105. date    91.03.30.17.55.03;    author paul;    state Exp;
  106. branches;
  107. next    5.30.0.19;
  108.  
  109. 5.30.0.19
  110. date    91.04.05.14.55.15;    author paul;    state Exp;
  111. branches;
  112. next    5.30.0.20;
  113.  
  114. 5.30.0.20
  115. date    91.04.11.15.11.47;    author paul;    state Exp;
  116. branches;
  117. next    5.30.0.21;
  118.  
  119. 5.30.0.21
  120. date    91.05.18.17.37.59;    author paul;    state Exp;
  121. branches;
  122. next    5.30.0.22;
  123.  
  124. 5.30.0.22
  125. date    91.05.20.19.24.12;    author paul;    state Exp;
  126. branches;
  127. next    5.30.0.23;
  128.  
  129. 5.30.0.23
  130. date    91.05.20.22.31.10;    author paul;    state Exp;
  131. branches;
  132. next    5.30.0.24;
  133.  
  134. 5.30.0.24
  135. date    91.05.23.21.39.58;    author paul;    state Exp;
  136. branches;
  137. next    5.30.0.25;
  138.  
  139. 5.30.0.25
  140. date    91.05.24.22.35.24;    author paul;    state Exp;
  141. branches;
  142. next    5.30.0.26;
  143.  
  144. 5.30.0.26
  145. date    91.06.01.22.18.25;    author paul;    state Exp;
  146. branches;
  147. next    5.30.0.27;
  148.  
  149. 5.30.0.27
  150. date    91.06.08.14.51.14;    author paul;    state Exp;
  151. branches;
  152. next    5.30.0.28;
  153.  
  154. 5.30.0.28
  155. date    91.06.24.14.26.25;    author paul;    state Exp;
  156. branches;
  157. next    ;
  158.  
  159.  
  160. desc
  161. @@
  162.  
  163.  
  164. 5.30
  165. log
  166. @5.64 Berkeley release
  167. @
  168. text
  169. @/*
  170.  * Copyright (c) 1983 Eric P. Allman
  171.  * Copyright (c) 1988 Regents of the University of California.
  172.  * All rights reserved.
  173.  *
  174.  * Redistribution and use in source and binary forms are permitted provided
  175.  * that: (1) source distributions retain this entire copyright notice and
  176.  * comment, and (2) distributions including binaries display the following
  177.  * acknowledgement:  ``This product includes software developed by the
  178.  * University of California, Berkeley and its contributors'' in the
  179.  * documentation or other materials provided with the distribution and in
  180.  * all advertising materials mentioning features or use of this software.
  181.  * Neither the name of the University nor the names of its contributors may
  182.  * be used to endorse or promote products derived from this software without
  183.  * specific prior written permission.
  184.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  185.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  186.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  187.  */
  188.  
  189. # include "sendmail.h"
  190.  
  191. #ifndef lint
  192. #ifdef QUEUE
  193. static char sccsid[] = "@@(#)queue.c    5.30 (Berkeley) 6/1/90 (with queueing)";
  194. #else
  195. static char sccsid[] = "@@(#)queue.c    5.30 (Berkeley) 6/1/90 (without queueing)";
  196. #endif
  197. #endif /* not lint */
  198.  
  199. # include <sys/stat.h>
  200. # include <sys/dir.h>
  201. # include <sys/file.h>
  202. # include <signal.h>
  203. # include <errno.h>
  204. # include <pwd.h>
  205.  
  206. # ifdef QUEUE
  207.  
  208. /*
  209. **  Work queue.
  210. */
  211.  
  212. struct work
  213. {
  214.     char        *w_name;    /* name of control file */
  215.     long        w_pri;        /* priority of message, see below */
  216.     time_t        w_ctime;    /* creation time of message */
  217.     struct work    *w_next;    /* next in queue */
  218. };
  219.  
  220. typedef struct work    WORK;
  221. extern int la;
  222.  
  223. WORK    *WorkQ;            /* queue of things to be done */
  224. /*
  225. **  QUEUEUP -- queue a message up for future transmission.
  226. **
  227. **    Parameters:
  228. **        e -- the envelope to queue up.
  229. **        queueall -- if TRUE, queue all addresses, rather than
  230. **            just those with the QQUEUEUP flag set.
  231. **        announce -- if TRUE, tell when you are queueing up.
  232. **
  233. **    Returns:
  234. **        locked FILE* to q file
  235. **
  236. **    Side Effects:
  237. **        The current request are saved in a control file.
  238. */
  239.  
  240. FILE *
  241. queueup(e, queueall, announce)
  242.     register ENVELOPE *e;
  243.     bool queueall;
  244.     bool announce;
  245. {
  246.     char *qf;
  247.     char buf[MAXLINE], tf[MAXLINE];
  248.     register FILE *tfp;
  249.     register HDR *h;
  250.     register ADDRESS *q;
  251.     MAILER nullmailer;
  252.     int fd, ret;
  253.  
  254.     /*
  255.     **  Create control file.
  256.     */
  257.  
  258.     do {
  259.         strcpy(tf, queuename(e, 't'));
  260.         fd = open(tf, O_CREAT|O_WRONLY|O_EXCL, FileMode);
  261.         if (fd < 0) {
  262.             if ( errno != EEXIST) {
  263.                 syserr("queueup: cannot create temp file %s",
  264.                     tf);
  265.                 return NULL;
  266.             }
  267.         } else {
  268.             if (flock(fd, LOCK_EX|LOCK_NB) < 0) {
  269.                 if (errno != EWOULDBLOCK)
  270.                     syserr("cannot flock(%s)", tf);
  271.                 close(fd);
  272.                 fd = -1;
  273.             }
  274.         }
  275.     } while (fd < 0);
  276.  
  277.     tfp = fdopen(fd, "w");
  278.  
  279.     if (tTd(40, 1))
  280.         printf("queueing %s\n", e->e_id);
  281.  
  282.     /*
  283.     **  If there is no data file yet, create one.
  284.     */
  285.  
  286.     if (e->e_df == NULL)
  287.     {
  288.         register FILE *dfp;
  289.         extern putbody();
  290.  
  291.         e->e_df = newstr(queuename(e, 'd'));
  292.         fd = open(e->e_df, O_WRONLY|O_CREAT, FileMode);
  293.         if (fd < 0)
  294.         {
  295.             syserr("queueup: cannot create %s", e->e_df);
  296.             (void) fclose(tfp);
  297.             return NULL;
  298.         }
  299.         dfp = fdopen(fd, "w");
  300.         (*e->e_putbody)(dfp, ProgMailer, e);
  301.         (void) fclose(dfp);
  302.         e->e_putbody = putbody;
  303.     }
  304.  
  305.     /*
  306.     **  Output future work requests.
  307.     **    Priority and creation time should be first, since
  308.     **    they are required by orderq.
  309.     */
  310.  
  311.     /* output message priority */
  312.     fprintf(tfp, "P%ld\n", e->e_msgpriority);
  313.  
  314.     /* output creation time */
  315.     fprintf(tfp, "T%ld\n", e->e_ctime);
  316.  
  317.     /* output name of data file */
  318.     fprintf(tfp, "D%s\n", e->e_df);
  319.  
  320.     /* message from envelope, if it exists */
  321.     if (e->e_message != NULL)
  322.         fprintf(tfp, "M%s\n", e->e_message);
  323.  
  324.     /* output name of sender */
  325.     fprintf(tfp, "S%s\n", e->e_from.q_paddr);
  326.  
  327.     /* output list of recipient addresses */
  328.     for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  329.     {
  330.         if (queueall ? !bitset(QDONTSEND, q->q_flags) :
  331.                    bitset(QQUEUEUP, q->q_flags))
  332.         {
  333.             char *ctluser, *getctluser();
  334.  
  335.             if ((ctluser = getctluser(q)) != NULL)
  336.                 fprintf(tfp, "C%s\n", ctluser);
  337.             fprintf(tfp, "R%s\n", q->q_paddr);
  338.             if (announce)
  339.             {
  340.                 e->e_to = q->q_paddr;
  341.                 message(Arpa_Info, "queued");
  342.                 if (LogLevel > 4)
  343.                     logdelivery("queued");
  344.                 e->e_to = NULL;
  345.             }
  346.             if (tTd(40, 1))
  347.             {
  348.                 printf("queueing ");
  349.                 printaddr(q, FALSE);
  350.             }
  351.         }
  352.     }
  353.  
  354.     /* output list of error recipients */
  355.     for (q = e->e_errorqueue; q != NULL; q = q->q_next)
  356.     {
  357.         if (!bitset(QDONTSEND, q->q_flags))
  358.         {
  359.             char *ctluser, *getctluser();
  360.  
  361.             if ((ctluser = getctluser(q)) != NULL)
  362.                 fprintf(tfp, "C%s\n", ctluser);
  363.             fprintf(tfp, "E%s\n", q->q_paddr);
  364.         }
  365.     }
  366.  
  367.     /*
  368.     **  Output headers for this message.
  369.     **    Expand macros completely here.  Queue run will deal with
  370.     **    everything as absolute headers.
  371.     **        All headers that must be relative to the recipient
  372.     **        can be cracked later.
  373.     **    We set up a "null mailer" -- i.e., a mailer that will have
  374.     **    no effect on the addresses as they are output.
  375.     */
  376.  
  377.     bzero((char *) &nullmailer, sizeof nullmailer);
  378.     nullmailer.m_r_rwset = nullmailer.m_s_rwset = -1;
  379.     nullmailer.m_eol = "\n";
  380.  
  381.     define('g', "\001f", e);
  382.     for (h = e->e_header; h != NULL; h = h->h_link)
  383.     {
  384.         extern bool bitzerop();
  385.  
  386.         /* don't output null headers */
  387.         if (h->h_value == NULL || h->h_value[0] == '\0')
  388.             continue;
  389.  
  390.         /* don't output resent headers on non-resent messages */
  391.         if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
  392.             continue;
  393.  
  394.         /* output this header */
  395.         fprintf(tfp, "H");
  396.  
  397.         /* if conditional, output the set of conditions */
  398.         if (!bitzerop(h->h_mflags) && bitset(H_CHECK|H_ACHECK, h->h_flags))
  399.         {
  400.             int j;
  401.  
  402.             (void) putc('?', tfp);
  403.             for (j = '\0'; j <= '\177'; j++)
  404.                 if (bitnset(j, h->h_mflags))
  405.                     (void) putc(j, tfp);
  406.             (void) putc('?', tfp);
  407.         }
  408.  
  409.         /* output the header: expand macros, convert addresses */
  410.         if (bitset(H_DEFAULT, h->h_flags))
  411.         {
  412.             (void) expand(h->h_value, buf, &buf[sizeof buf], e);
  413.             fprintf(tfp, "%s: %s\n", h->h_field, buf);
  414.         }
  415.         else if (bitset(H_FROM|H_RCPT, h->h_flags))
  416.         {
  417.             commaize(h, h->h_value, tfp, bitset(EF_OLDSTYLE, e->e_flags),
  418.                  &nullmailer);
  419.         }
  420.         else
  421.             fprintf(tfp, "%s: %s\n", h->h_field, h->h_value);
  422.     }
  423.  
  424.     /*
  425.     **  Clean up.
  426.     */
  427.  
  428.     qf = queuename(e, 'q');
  429.     if (rename(tf, qf) < 0)
  430.         syserr("cannot rename(%s, %s), df=%s", tf, qf, e->e_df);
  431.     errno = 0;
  432.  
  433. # ifdef LOG
  434.     /* save log info */
  435.     if (LogLevel > 15)
  436.         syslog(LOG_DEBUG, "%s: queueup, qf=%s, df=%s\n", e->e_id, qf, e->e_df);
  437. # endif LOG
  438.     fflush(tfp);
  439.     return tfp;
  440. }
  441. /*
  442. **  RUNQUEUE -- run the jobs in the queue.
  443. **
  444. **    Gets the stuff out of the queue in some presumably logical
  445. **    order and processes them.
  446. **
  447. **    Parameters:
  448. **        forkflag -- TRUE if the queue scanning should be done in
  449. **            a child process.  We double-fork so it is not our
  450. **            child and we don't have to clean up after it.
  451. **
  452. **    Returns:
  453. **        none.
  454. **
  455. **    Side Effects:
  456. **        runs things in the mail queue.
  457. */
  458.  
  459. runqueue(forkflag)
  460.     bool forkflag;
  461. {
  462.     extern bool shouldqueue();
  463.  
  464.     /*
  465.     **  If no work will ever be selected, don't even bother reading
  466.     **  the queue.
  467.     */
  468.  
  469.     la = getla();    /* get load average */
  470.  
  471.     if (shouldqueue(-100000000L))
  472.     {
  473.         if (Verbose)
  474.             printf("Skipping queue run -- load average too high\n");
  475.  
  476.         if (forkflag)
  477.             return;
  478.         finis();
  479.     }
  480.  
  481.     /*
  482.     **  See if we want to go off and do other useful work.
  483.     */
  484.  
  485.     if (forkflag)
  486.     {
  487.         int pid;
  488.  
  489.         pid = dofork();
  490.         if (pid != 0)
  491.         {
  492.             extern reapchild();
  493.  
  494.             /* parent -- pick up intermediate zombie */
  495. #ifndef SIGCHLD
  496.             (void) waitfor(pid);
  497. #else SIGCHLD
  498.             (void) signal(SIGCHLD, reapchild);
  499. #endif SIGCHLD
  500.             if (QueueIntvl != 0)
  501.                 (void) setevent(QueueIntvl, runqueue, TRUE);
  502.             return;
  503.         }
  504.         /* child -- double fork */
  505. #ifndef SIGCHLD
  506.         if (fork() != 0)
  507.             exit(EX_OK);
  508. #else SIGCHLD
  509.         (void) signal(SIGCHLD, SIG_DFL);
  510. #endif SIGCHLD
  511.     }
  512.  
  513.     setproctitle("running queue: %s", QueueDir);
  514.  
  515. # ifdef LOG
  516.     if (LogLevel > 11)
  517.         syslog(LOG_DEBUG, "runqueue %s, pid=%d", QueueDir, getpid());
  518. # endif LOG
  519.  
  520.     /*
  521.     **  Release any resources used by the daemon code.
  522.     */
  523.  
  524. # ifdef DAEMON
  525.     clrdaemon();
  526. # endif DAEMON
  527.  
  528.     /*
  529.     **  Make sure the alias database is open.
  530.     */
  531.  
  532.     initaliases(AliasFile, FALSE);
  533.  
  534.     /*
  535.     **  Start making passes through the queue.
  536.     **    First, read and sort the entire queue.
  537.     **    Then, process the work in that order.
  538.     **        But if you take too long, start over.
  539.     */
  540.  
  541.     /* order the existing work requests */
  542.     (void) orderq(FALSE);
  543.  
  544.     /* process them once at a time */
  545.     while (WorkQ != NULL)
  546.     {
  547.         WORK *w = WorkQ;
  548.  
  549.         WorkQ = WorkQ->w_next;
  550.         dowork(w);
  551.         free(w->w_name);
  552.         free((char *) w);
  553.     }
  554.  
  555.     /* exit without the usual cleanup */
  556.     exit(ExitStat);
  557. }
  558. /*
  559. **  ORDERQ -- order the work queue.
  560. **
  561. **    Parameters:
  562. **        doall -- if set, include everything in the queue (even
  563. **            the jobs that cannot be run because the load
  564. **            average is too high).  Otherwise, exclude those
  565. **            jobs.
  566. **
  567. **    Returns:
  568. **        The number of request in the queue (not necessarily
  569. **        the number of requests in WorkQ however).
  570. **
  571. **    Side Effects:
  572. **        Sets WorkQ to the queue of available work, in order.
  573. */
  574.  
  575. # define NEED_P        001
  576. # define NEED_T        002
  577.  
  578. orderq(doall)
  579.     bool doall;
  580. {
  581.     register struct direct *d;
  582.     register WORK *w;
  583.     DIR *f;
  584.     register int i;
  585.     WORK wlist[QUEUESIZE+1];
  586.     int wn = -1;
  587.     extern workcmpf();
  588.  
  589.     /* clear out old WorkQ */
  590.     for (w = WorkQ; w != NULL; )
  591.     {
  592.         register WORK *nw = w->w_next;
  593.  
  594.         WorkQ = nw;
  595.         free(w->w_name);
  596.         free((char *) w);
  597.         w = nw;
  598.     }
  599.  
  600.     /* open the queue directory */
  601.     f = opendir(".");
  602.     if (f == NULL)
  603.     {
  604.         syserr("orderq: cannot open \"%s\" as \".\"", QueueDir);
  605.         return (0);
  606.     }
  607.  
  608.     /*
  609.     **  Read the work directory.
  610.     */
  611.  
  612.     while ((d = readdir(f)) != NULL)
  613.     {
  614.         FILE *cf;
  615.         char lbuf[MAXNAME];
  616.  
  617.         /* is this an interesting entry? */
  618.         if (d->d_name[0] != 'q' || d->d_name[1] != 'f')
  619.             continue;
  620.  
  621.         /* yes -- open control file (if not too many files) */
  622.         if (++wn >= QUEUESIZE)
  623.             continue;
  624.         cf = fopen(d->d_name, "r");
  625.         if (cf == NULL)
  626.         {
  627.             /* this may be some random person sending hir msgs */
  628.             /* syserr("orderq: cannot open %s", cbuf); */
  629.             if (tTd(41, 2))
  630.                 printf("orderq: cannot open %s (%d)\n",
  631.                     d->d_name, errno);
  632.             errno = 0;
  633.             wn--;
  634.             continue;
  635.         }
  636.         w = &wlist[wn];
  637.         w->w_name = newstr(d->d_name);
  638.  
  639.         /* make sure jobs in creation don't clog queue */
  640.         w->w_pri = 0x7fffffff;
  641.         w->w_ctime = 0;
  642.  
  643.         /* extract useful information */
  644.         i = NEED_P | NEED_T;
  645.         while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL)
  646.         {
  647.             extern long atol();
  648.  
  649.             switch (lbuf[0])
  650.             {
  651.               case 'P':
  652.                 w->w_pri = atol(&lbuf[1]);
  653.                 i &= ~NEED_P;
  654.                 break;
  655.  
  656.               case 'T':
  657.                 w->w_ctime = atol(&lbuf[1]);
  658.                 i &= ~NEED_T;
  659.                 break;
  660.             }
  661.         }
  662.         (void) fclose(cf);
  663.  
  664.         if (!doall && shouldqueue(w->w_pri))
  665.         {
  666.             /* don't even bother sorting this job in */
  667.             wn--;
  668.         }
  669.     }
  670.     (void) closedir(f);
  671.     wn++;
  672.  
  673.     /*
  674.     **  Sort the work directory.
  675.     */
  676.  
  677.     qsort((char *) wlist, min(wn, QUEUESIZE), sizeof *wlist, workcmpf);
  678.  
  679.     /*
  680.     **  Convert the work list into canonical form.
  681.     **    Should be turning it into a list of envelopes here perhaps.
  682.     */
  683.  
  684.     WorkQ = NULL;
  685.     for (i = min(wn, QUEUESIZE); --i >= 0; )
  686.     {
  687.         w = (WORK *) xalloc(sizeof *w);
  688.         w->w_name = wlist[i].w_name;
  689.         w->w_pri = wlist[i].w_pri;
  690.         w->w_ctime = wlist[i].w_ctime;
  691.         w->w_next = WorkQ;
  692.         WorkQ = w;
  693.     }
  694.  
  695.     if (tTd(40, 1))
  696.     {
  697.         for (w = WorkQ; w != NULL; w = w->w_next)
  698.             printf("%32s: pri=%ld\n", w->w_name, w->w_pri);
  699.     }
  700.  
  701.     return (wn);
  702. }
  703. /*
  704. **  WORKCMPF -- compare function for ordering work.
  705. **
  706. **    Parameters:
  707. **        a -- the first argument.
  708. **        b -- the second argument.
  709. **
  710. **    Returns:
  711. **        -1 if a < b
  712. **         0 if a == b
  713. **        +1 if a > b
  714. **
  715. **    Side Effects:
  716. **        none.
  717. */
  718.  
  719. workcmpf(a, b)
  720.     register WORK *a;
  721.     register WORK *b;
  722. {
  723.     long pa = a->w_pri + a->w_ctime;
  724.     long pb = b->w_pri + b->w_ctime;
  725.  
  726.     if (pa == pb)
  727.         return (0);
  728.     else if (pa > pb)
  729.         return (1);
  730.     else
  731.         return (-1);
  732. }
  733. /*
  734. **  DOWORK -- do a work request.
  735. **
  736. **    Parameters:
  737. **        w -- the work request to be satisfied.
  738. **
  739. **    Returns:
  740. **        none.
  741. **
  742. **    Side Effects:
  743. **        The work request is satisfied if possible.
  744. */
  745.  
  746. dowork(w)
  747.     register WORK *w;
  748. {
  749.     register int i;
  750.     extern bool shouldqueue();
  751.  
  752.     if (tTd(40, 1))
  753.         printf("dowork: %s pri %ld\n", w->w_name, w->w_pri);
  754.  
  755.     /*
  756.     **  Ignore jobs that are too expensive for the moment.
  757.     */
  758.  
  759.     if (shouldqueue(w->w_pri))
  760.     {
  761.         if (Verbose)
  762.             printf("\nSkipping %s\n", w->w_name + 2);
  763.         return;
  764.     }
  765.  
  766.     /*
  767.     **  Fork for work.
  768.     */
  769.  
  770.     if (ForkQueueRuns)
  771.     {
  772.         i = fork();
  773.         if (i < 0)
  774.         {
  775.             syserr("dowork: cannot fork");
  776.             return;
  777.         }
  778.     }
  779.     else
  780.     {
  781.         i = 0;
  782.     }
  783.  
  784.     if (i == 0)
  785.     {
  786.         FILE *qflock, *readqf();
  787.         /*
  788.         **  CHILD
  789.         **    Lock the control file to avoid duplicate deliveries.
  790.         **        Then run the file as though we had just read it.
  791.         **    We save an idea of the temporary name so we
  792.         **        can recover on interrupt.
  793.         */
  794.  
  795.         /* set basic modes, etc. */
  796.         (void) alarm(0);
  797.         clearenvelope(CurEnv, FALSE);
  798.         QueueRun = TRUE;
  799.         ErrorMode = EM_MAIL;
  800.         CurEnv->e_id = &w->w_name[2];
  801. # ifdef LOG
  802.         if (LogLevel > 11)
  803.             syslog(LOG_DEBUG, "%s: dowork, pid=%d", CurEnv->e_id,
  804.                    getpid());
  805. # endif LOG
  806.  
  807.         /* don't use the headers from sendmail.cf... */
  808.         CurEnv->e_header = NULL;
  809.  
  810.         /* read the queue control file */
  811.         /*  and lock the control file during processing */
  812.         if ((qflock=readqf(CurEnv, TRUE)) == NULL)
  813.         {
  814.             if (ForkQueueRuns)
  815.                 exit(EX_OK);
  816.             else
  817.                 return;
  818.         }
  819.  
  820.         CurEnv->e_flags |= EF_INQUEUE;
  821.         eatheader(CurEnv);
  822.  
  823.         /* do the delivery */
  824.         if (!bitset(EF_FATALERRS, CurEnv->e_flags))
  825.             sendall(CurEnv, SM_DELIVER);
  826.  
  827.         /* finish up and exit */
  828.         if (ForkQueueRuns)
  829.             finis();
  830.         else
  831.             dropenvelope(CurEnv);
  832.         fclose(qflock);
  833.     }
  834.     else
  835.     {
  836.         /*
  837.         **  Parent -- pick up results.
  838.         */
  839.  
  840.         errno = 0;
  841.         (void) waitfor(i);
  842.     }
  843. }
  844. /*
  845. **  READQF -- read queue file and set up environment.
  846. **
  847. **    Parameters:
  848. **        e -- the envelope of the job to run.
  849. **        full -- if set, read in all information.  Otherwise just
  850. **            read in info needed for a queue print.
  851. **
  852. **    Returns:
  853. **        FILE * pointing to flock()ed fd so it can be closed
  854. **        after the mail is delivered
  855. **
  856. **    Side Effects:
  857. **        cf is read and created as the current job, as though
  858. **        we had been invoked by argument.
  859. */
  860.  
  861. FILE *
  862. readqf(e, full)
  863.     register ENVELOPE *e;
  864.     bool full;
  865. {
  866.     char *qf;
  867.     register FILE *qfp;
  868.     char buf[MAXFIELD];
  869.     extern char *fgetfolded();
  870.     extern long atol();
  871.     int gotctluser = 0;
  872.     int fd;
  873.  
  874.     /*
  875.     **  Read and process the file.
  876.     */
  877.  
  878.     qf = queuename(e, 'q');
  879.     qfp = fopen(qf, "r");
  880.     if (qfp == NULL)
  881.     {
  882.         if (errno != ENOENT)
  883.             syserr("readqf: no control file %s", qf);
  884.         return NULL;
  885.     }
  886.  
  887.     if (flock(fileno(qfp), LOCK_EX|LOCK_NB) < 0)
  888.     {
  889. # ifdef LOG
  890.         /* being processed by another queuer */
  891.         if (Verbose)
  892.             printf("%s: locked\n", CurEnv->e_id);
  893. # endif LOG
  894.         (void) fclose(qfp);
  895.         return NULL;
  896.     }
  897.  
  898.     /* do basic system initialization */
  899.     initsys();
  900.  
  901.     FileName = qf;
  902.     LineNumber = 0;
  903.     if (Verbose && full)
  904.         printf("\nRunning %s\n", e->e_id);
  905.     while (fgetfolded(buf, sizeof buf, qfp) != NULL)
  906.     {
  907.         if (tTd(40, 4))
  908.             printf("+++++ %s\n", buf);
  909.         switch (buf[0])
  910.         {
  911.           case 'C':        /* specify controlling user */
  912.             setctluser(&buf[1]);
  913.             gotctluser = 1;
  914.             break;
  915.  
  916.           case 'R':        /* specify recipient */
  917.             sendtolist(&buf[1], (ADDRESS *) NULL, &e->e_sendqueue);
  918.             break;
  919.  
  920.           case 'E':        /* specify error recipient */
  921.             sendtolist(&buf[1], (ADDRESS *) NULL, &e->e_errorqueue);
  922.             break;
  923.  
  924.           case 'H':        /* header */
  925.             if (full)
  926.                 (void) chompheader(&buf[1], FALSE);
  927.             break;
  928.  
  929.           case 'M':        /* message */
  930.             e->e_message = newstr(&buf[1]);
  931.             break;
  932.  
  933.           case 'S':        /* sender */
  934.             setsender(newstr(&buf[1]));
  935.             break;
  936.  
  937.           case 'D':        /* data file name */
  938.             if (!full)
  939.                 break;
  940.             e->e_df = newstr(&buf[1]);
  941.             e->e_dfp = fopen(e->e_df, "r");
  942.             if (e->e_dfp == NULL)
  943.                 syserr("readqf: cannot open %s", e->e_df);
  944.             break;
  945.  
  946.           case 'T':        /* init time */
  947.             e->e_ctime = atol(&buf[1]);
  948.             break;
  949.  
  950.           case 'P':        /* message priority */
  951.             e->e_msgpriority = atol(&buf[1]) + WkTimeFact;
  952.             break;
  953.  
  954.           case '\0':        /* blank line; ignore */
  955.             break;
  956.  
  957.           default:
  958.             syserr("readqf(%s:%d): bad line \"%s\"", e->e_id,
  959.                 LineNumber, buf);
  960.             break;
  961.         }
  962.         /*
  963.         **  The `C' queue file command operates on the next line,
  964.         **  so we use "gotctluser" to maintain state as follows:
  965.         **      0 - no controlling user,
  966.         **      1 - controlling user has been set but not used,
  967.         **      2 - controlling user must be used on next iteration.
  968.         */
  969.         if (gotctluser == 1)
  970.             gotctluser++;
  971.         else if (gotctluser == 2)
  972.         {
  973.             clrctluser();
  974.             gotctluser = 0;
  975.         }
  976.     }
  977.  
  978.     /* clear controlling user in case we break out prematurely */
  979.     clrctluser();
  980.  
  981.     FileName = NULL;
  982.  
  983.     /*
  984.     **  If we haven't read any lines, this queue file is empty.
  985.     **  Arrange to remove it without referencing any null pointers.
  986.     */
  987.  
  988.     if (LineNumber == 0)
  989.     {
  990.         errno = 0;
  991.         e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE;
  992.     }
  993.     return qfp;
  994. }
  995. /*
  996. **  PRINTQUEUE -- print out a representation of the mail queue
  997. **
  998. **    Parameters:
  999. **        none.
  1000. **
  1001. **    Returns:
  1002. **        none.
  1003. **
  1004. **    Side Effects:
  1005. **        Prints a listing of the mail queue on the standard output.
  1006. */
  1007.  
  1008. printqueue()
  1009. {
  1010.     register WORK *w;
  1011.     FILE *f;
  1012.     int nrequests;
  1013.     char buf[MAXLINE];
  1014.     char cbuf[MAXLINE];
  1015.  
  1016.     /*
  1017.     **  Read and order the queue.
  1018.     */
  1019.  
  1020.     nrequests = orderq(TRUE);
  1021.  
  1022.     /*
  1023.     **  Print the work list that we have read.
  1024.     */
  1025.  
  1026.     /* first see if there is anything */
  1027.     if (nrequests <= 0)
  1028.     {
  1029.         printf("Mail queue is empty\n");
  1030.         return;
  1031.     }
  1032.  
  1033.     la = getla();    /* get load average */
  1034.  
  1035.     printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s");
  1036.     if (nrequests > QUEUESIZE)
  1037.         printf(", only %d printed", QUEUESIZE);
  1038.     if (Verbose)
  1039.         printf(")\n--QID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n");
  1040.     else
  1041.         printf(")\n--QID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n");
  1042.     for (w = WorkQ; w != NULL; w = w->w_next)
  1043.     {
  1044.         struct stat st;
  1045.         auto time_t submittime = 0;
  1046.         long dfsize = -1;
  1047.         char message[MAXLINE];
  1048.         extern bool shouldqueue();
  1049.  
  1050.         f = fopen(w->w_name, "r");
  1051.         if (f == NULL)
  1052.         {
  1053.             errno = 0;
  1054.             continue;
  1055.         }
  1056.         printf("%7s", w->w_name + 2);
  1057.         if (flock(fileno(f), LOCK_SH|LOCK_NB) < 0)
  1058.             printf("*");
  1059.         else if (shouldqueue(w->w_pri))
  1060.             printf("X");
  1061.         else
  1062.             printf(" ");
  1063.         errno = 0;
  1064.  
  1065.         message[0] = '\0';
  1066.         cbuf[0] = '\0';
  1067.         while (fgets(buf, sizeof buf, f) != NULL)
  1068.         {
  1069.             fixcrlf(buf, TRUE);
  1070.             switch (buf[0])
  1071.             {
  1072.               case 'M':    /* error message */
  1073.                 (void) strcpy(message, &buf[1]);
  1074.                 break;
  1075.  
  1076.               case 'S':    /* sender name */
  1077.                 if (Verbose)
  1078.                     printf("%8ld %10ld %.12s %.38s", dfsize,
  1079.                         w->w_pri, ctime(&submittime) + 4,
  1080.                         &buf[1]);
  1081.                 else
  1082.                     printf("%8ld %.16s %.45s", dfsize,
  1083.                         ctime(&submittime), &buf[1]);
  1084.                 if (message[0] != '\0')
  1085.                     printf("\n\t\t (%.60s)", message);
  1086.                 break;
  1087.               case 'C':    /* controlling user */
  1088.                 if (strlen(buf) < MAXLINE-3)    /* sanity */
  1089.                     (void) strcat(buf, ") ");
  1090.                 cbuf[0] = cbuf[1] = '(';
  1091.                 (void) strncpy(&cbuf[2], &buf[1], MAXLINE-1);
  1092.                 cbuf[MAXLINE-1] = '\0';
  1093.                 break;
  1094.  
  1095.               case 'R':    /* recipient name */
  1096.                 if (cbuf[0] != '\0') {
  1097.                     /* prepend controlling user to `buf' */
  1098.                     (void) strncat(cbuf, &buf[1],
  1099.                                   MAXLINE-strlen(cbuf));
  1100.                     cbuf[MAXLINE-1] = '\0';
  1101.                     (void) strcpy(buf, cbuf);
  1102.                     cbuf[0] = '\0';
  1103.                 }
  1104.                 if (Verbose)
  1105.                     printf("\n\t\t\t\t\t %.38s", &buf[1]);
  1106.                 else
  1107.                     printf("\n\t\t\t\t  %.45s", &buf[1]);
  1108.                 break;
  1109.  
  1110.               case 'T':    /* creation time */
  1111.                 submittime = atol(&buf[1]);
  1112.                 break;
  1113.  
  1114.               case 'D':    /* data file name */
  1115.                 if (stat(&buf[1], &st) >= 0)
  1116.                     dfsize = st.st_size;
  1117.                 break;
  1118.             }
  1119.         }
  1120.         if (submittime == (time_t) 0)
  1121.             printf(" (no control file)");
  1122.         printf("\n");
  1123.         (void) fclose(f);
  1124.     }
  1125. }
  1126.  
  1127. # endif QUEUE
  1128. /*
  1129. **  QUEUENAME -- build a file name in the queue directory for this envelope.
  1130. **
  1131. **    Assigns an id code if one does not already exist.
  1132. **    This code is very careful to avoid trashing existing files
  1133. **    under any circumstances.
  1134. **
  1135. **    Parameters:
  1136. **        e -- envelope to build it in/from.
  1137. **        type -- the file type, used as the first character
  1138. **            of the file name.
  1139. **
  1140. **    Returns:
  1141. **        a pointer to the new file name (in a static buffer).
  1142. **
  1143. **    Side Effects:
  1144. **        Will create the qf file if no id code is
  1145. **        already assigned.  This will cause the envelope
  1146. **        to be modified.
  1147. */
  1148.  
  1149. char *
  1150. queuename(e, type)
  1151.     register ENVELOPE *e;
  1152.     char type;
  1153. {
  1154.     static char buf[MAXNAME];
  1155.     static int pid = -1;
  1156.     char c1 = 'A';
  1157.     char c2 = 'A';
  1158.  
  1159.     if (e->e_id == NULL)
  1160.     {
  1161.         char qf[20];
  1162.  
  1163.         /* find a unique id */
  1164.         if (pid != getpid())
  1165.         {
  1166.             /* new process -- start back at "AA" */
  1167.             pid = getpid();
  1168.             c1 = 'A';
  1169.             c2 = 'A' - 1;
  1170.         }
  1171.         (void) sprintf(qf, "qfAA%05d", pid);
  1172.  
  1173.         while (c1 < '~' || c2 < 'Z')
  1174.         {
  1175.             int i;
  1176.  
  1177.             if (c2 >= 'Z')
  1178.             {
  1179.                 c1++;
  1180.                 c2 = 'A' - 1;
  1181.             }
  1182.             qf[2] = c1;
  1183.             qf[3] = ++c2;
  1184.             if (tTd(7, 20))
  1185.                 printf("queuename: trying \"%s\"\n", qf);
  1186.  
  1187.             i = open(qf, O_WRONLY|O_CREAT|O_EXCL, FileMode);
  1188.             if (i < 0) {
  1189.                 if (errno != EEXIST) {
  1190.                     syserr("queuename: Cannot create \"%s\" in \"%s\"",
  1191.                         qf, QueueDir);
  1192.                     exit(EX_UNAVAILABLE);
  1193.                 }
  1194.             } else {
  1195.                 (void) close(i);
  1196.                 break;
  1197.             }
  1198.         }
  1199.         if (c1 >= '~' && c2 >= 'Z')
  1200.         {
  1201.             syserr("queuename: Cannot create \"%s\" in \"%s\"",
  1202.                 qf, QueueDir);
  1203.             exit(EX_OSERR);
  1204.         }
  1205.         e->e_id = newstr(&qf[2]);
  1206.         define('i', e->e_id, e);
  1207.         if (tTd(7, 1))
  1208.             printf("queuename: assigned id %s, env=%x\n", e->e_id, e);
  1209. # ifdef LOG
  1210.         if (LogLevel > 16)
  1211.             syslog(LOG_DEBUG, "%s: assigned id", e->e_id);
  1212. # endif LOG
  1213.     }
  1214.  
  1215.     if (type == '\0')
  1216.         return (NULL);
  1217.     (void) sprintf(buf, "%cf%s", type, e->e_id);
  1218.     if (tTd(7, 2))
  1219.         printf("queuename: %s\n", buf);
  1220.     return (buf);
  1221. }
  1222. /*
  1223. **  UNLOCKQUEUE -- unlock the queue entry for a specified envelope
  1224. **
  1225. **    Parameters:
  1226. **        e -- the envelope to unlock.
  1227. **
  1228. **    Returns:
  1229. **        none
  1230. **
  1231. **    Side Effects:
  1232. **        unlocks the queue for `e'.
  1233. */
  1234.  
  1235. unlockqueue(e)
  1236.     ENVELOPE *e;
  1237. {
  1238.     /* remove the transcript */
  1239. # ifdef LOG
  1240.     if (LogLevel > 19)
  1241.         syslog(LOG_DEBUG, "%s: unlock", e->e_id);
  1242. # endif LOG
  1243.     if (!tTd(51, 4))
  1244.         xunlink(queuename(e, 'x'));
  1245.  
  1246. }
  1247. /*
  1248. **  GETCTLUSER -- return controlling user if mailing to prog or file
  1249. **
  1250. **    Check for a "|" or "/" at the beginning of the address.  If
  1251. **    found, return a controlling username.
  1252. **
  1253. **    Parameters:
  1254. **        a - the address to check out
  1255. **
  1256. **    Returns:
  1257. **        Either NULL, if we werent mailing to a program or file,
  1258. **        or a controlling user name (possibly in getpwuid's
  1259. **        static buffer).
  1260. **
  1261. **    Side Effects:
  1262. **        none.
  1263. */
  1264.  
  1265. char *
  1266. getctluser(a)
  1267.     ADDRESS *a;
  1268. {
  1269.     extern ADDRESS *getctladdr();
  1270.     struct passwd *pw;
  1271.     char *retstr;
  1272.  
  1273.     /*
  1274.     **  Get unquoted user for file, program or user.name check.
  1275.     **  N.B. remove this code block to always emit controlling
  1276.     **  addresses (at the expense of backward compatibility).
  1277.     */
  1278.  
  1279.     {
  1280.         char buf[MAXNAME];
  1281.         (void) strncpy(buf, a->q_paddr, MAXNAME);
  1282.         buf[MAXNAME-1] = '\0';
  1283.         stripquotes(buf, TRUE);
  1284.  
  1285.         if (buf[0] != '|' && buf[0] != '/')
  1286.             return((char *)NULL);
  1287.     }
  1288.  
  1289.     a = getctladdr(a);        /* find controlling address */
  1290.  
  1291.     if (a != NULL && a->q_uid != 0 && (pw = getpwuid(a->q_uid)) != NULL)
  1292.         retstr = pw->pw_name;
  1293.     else                /* use default user */
  1294.         retstr = DefUser;
  1295.  
  1296.     if (tTd(40, 5))
  1297.         printf("Set controlling user for `%s' to `%s'\n",
  1298.                (a == NULL)? "<null>": a->q_paddr, retstr);
  1299.  
  1300.     return(retstr);
  1301. }
  1302. /*
  1303. **  SETCTLUSER - sets `CtlUser' to controlling user
  1304. **  CLRCTLUSER - clears controlling user (no params, nothing returned)
  1305. **
  1306. **    These routines manipulate `CtlUser'.
  1307. **
  1308. **    Parameters:
  1309. **        str  - controlling user as passed to setctluser()
  1310. **
  1311. **    Returns:
  1312. **        None.
  1313. **
  1314. **    Side Effects:
  1315. **        `CtlUser' is changed.
  1316. */
  1317.  
  1318. static char CtlUser[MAXNAME];
  1319.  
  1320. setctluser(str)
  1321. register char *str;
  1322. {
  1323.     (void) strncpy(CtlUser, str, MAXNAME);
  1324.     CtlUser[MAXNAME-1] = '\0';
  1325. }
  1326.  
  1327. clrctluser()
  1328. {
  1329.     CtlUser[0] = '\0';
  1330. }
  1331.  
  1332. /*
  1333. **  SETCTLADDR -- create a controlling address
  1334. **
  1335. **    If global variable `CtlUser' is set and we are given a valid
  1336. **    address, make that address a controlling address; change the
  1337. **    `q_uid', `q_gid', and `q_ruser' fields and set QGOODUID.
  1338. **
  1339. **    Parameters:
  1340. **        a - address for which control uid/gid info may apply
  1341. **
  1342. **    Returns:
  1343. **        None.    
  1344. **
  1345. **    Side Effects:
  1346. **        Fills in uid/gid fields in address and sets QGOODUID
  1347. **        flag if appropriate.
  1348. */
  1349.  
  1350. setctladdr(a)
  1351.     ADDRESS *a;
  1352. {
  1353.     struct passwd *pw;
  1354.  
  1355.     /*
  1356.     **  If there is no current controlling user, or we were passed a
  1357.     **  NULL addr ptr or we already have a controlling user, return.
  1358.     */
  1359.  
  1360.     if (CtlUser[0] == '\0' || a == NULL || a->q_ruser)
  1361.         return;
  1362.  
  1363.     /*
  1364.     **  Set up addr fields for controlling user.  If `CtlUser' is no
  1365.     **  longer valid, use the default user/group.
  1366.     */
  1367.  
  1368.     if ((pw = getpwnam(CtlUser)) != NULL)
  1369.     {
  1370.         if (a->q_home)
  1371.             free(a->q_home);
  1372.         a->q_home = newstr(pw->pw_dir);
  1373.         a->q_uid = pw->pw_uid;
  1374.         a->q_gid = pw->pw_gid;
  1375.         a->q_ruser = newstr(CtlUser);
  1376.     }
  1377.     else
  1378.     {
  1379.         a->q_uid = DefUid;
  1380.         a->q_gid = DefGid;
  1381.         a->q_ruser = newstr(DefUser);
  1382.     }
  1383.  
  1384.     a->q_flags |= QGOODUID;        /* flag as a "ctladdr"  */
  1385.  
  1386.     if (tTd(40, 5))
  1387.         printf("Restored controlling user for `%s' to `%s'\n",
  1388.                a->q_paddr, a->q_ruser);
  1389. }
  1390. @
  1391.  
  1392.  
  1393. 5.30.0.1
  1394. log
  1395. @IDA patches
  1396. @
  1397. text
  1398. @d210 1
  1399. a210 2
  1400.     nullmailer.m_re_rwset = nullmailer.m_se_rwset = -1;
  1401.     nullmailer.m_rh_rwset = nullmailer.m_sh_rwset = -1;
  1402. d269 1
  1403. a269 1
  1404. # endif /* LOG */
  1405. d329 1
  1406. a329 1
  1407. #else /* SIGCHLD */
  1408. d331 1
  1409. a331 1
  1410. #endif /* !SIGCHLD */
  1411. d340 1
  1412. a340 1
  1413. #else /* SIGCHLD */
  1414. d342 1
  1415. a342 1
  1416. #endif /* !SIGCHLD */
  1417. d350 1
  1418. a350 1
  1419. # endif /* LOG */
  1420. d358 1
  1421. a358 1
  1422. # endif /* DAEMON */
  1423. d364 1
  1424. a364 1
  1425.     initaliases(FALSE);
  1426. d637 1
  1427. a637 1
  1428. # endif /* LOG */
  1429. d959 1
  1430. a959 1
  1431. # endif /* QUEUE */
  1432. d1044 1
  1433. a1044 1
  1434. # endif /* LOG */
  1435. d1074 1
  1436. a1074 1
  1437. # endif /* LOG */
  1438. @
  1439.  
  1440.  
  1441. 5.30.0.2
  1442. log
  1443. @Date: Wed, 20 Jun 90 15:39:37 -0400 (EDT)
  1444. From: Craig_Everhart@@transarc.com
  1445. To: paul@@uxc.cso.uiuc.edu (Paul Pomes - UofIllinois CSO)
  1446. Subject: Re: Sendmail V5.64 + IDA enhancements available for anon-FTP
  1447.  
  1448. Here's a sendmail patch for you that I've been sending around.  I've
  1449. been running it for years, and it was only when Peter Neumann had such
  1450. trouble with RISKS duplications that I decided to try to propagate it.
  1451.  
  1452. The problem addressed by the fix is that if sendmail delivers to a long
  1453. address list (in a single request) but crashes in the middle, it has no
  1454. record of the successful deliveries that it has made so far, so when it
  1455. eventually gets around to retrying that request, it re-delivers to all
  1456. the addresses to which it had been able to deliver earlier.  Not only
  1457. does this generate duplicate mail, but the re-delivery process also
  1458. requires additional queue processing time, so that it might continue to
  1459. take a long time even to attempt delivery to the last address in the
  1460. list.
  1461.  
  1462. The solution that this patch builds is simple and not very expensive:
  1463. after every successful mail delivery, the qf* file is rewritten,
  1464. omitting the recipient to whom delivery was successful.  The qf* file
  1465. gets shorter even as the request is processed.  A crash in the middle of
  1466. processing the list will result in duplicate delivery to at most one
  1467. host.  It doesn't require that much time to rewrite the qf* file;
  1468. certainly less time than the delivery itself takes.
  1469.  
  1470. The only real disadvantage I can imagine is that my sendmail sources
  1471. have diverged in many ways from a UCB version of about 1986. 
  1472. Nonetheless, it shouldn't be difficult to install this change.
  1473.  
  1474. As you can see, this change works by adding an additional flag parameter
  1475. to queueup(), then calling queueup() (from sendall()) with this
  1476. parameter set sometimes.  The queueup() flag parameter controls which
  1477. addresses are rewritten, looking at different flags.
  1478.  
  1479. So here's the patch.  I hope that you find it useful.  I look forward to
  1480. your reply.
  1481.  
  1482.         Thanks,
  1483.         Craig Everhart
  1484. @
  1485. text
  1486. @a63 4
  1487. ** (CFE)        Checkpoint -- if TRUE, we're doing a checkpoint of a
  1488. **            list currently being delivered.  Write the
  1489. **            addresses not yet tried as well as the queued
  1490. **            addresses.
  1491. d73 1
  1492. a73 1
  1493. queueup(e, queueall, announce, Checkpoint)
  1494. a76 1
  1495.     bool Checkpoint;
  1496. d162 2
  1497. a163 12
  1498.         int writeit;
  1499.  
  1500.         if (Checkpoint) {    /* Delete the already-sent addresses. */
  1501.             writeit = TRUE;
  1502.             if (bitset(QDONTSEND, q->q_flags)
  1503.               && !bitset(QQUEUEUP, q->q_flags)
  1504.               && !bitset(QBADADDR, q->q_flags)) writeit = FALSE;
  1505.         } else if (queueall)
  1506.             writeit = !bitset(QDONTSEND, q->q_flags);
  1507.         else
  1508.             writeit = bitset(QQUEUEUP, q->q_flags);
  1509.         if (writeit)
  1510. @
  1511.  
  1512.  
  1513. 5.30.0.3
  1514. log
  1515. @Patches for HP-UX from Andy Linton <root@@comp.vuw.ac.nz>.  Thanks Andy!
  1516. @
  1517. text
  1518. @a726 7
  1519. #if defined(hpux)
  1520.         /*
  1521.          * We can't get an exclusive lock on a file that
  1522.          * isn't opened for writing - sigh!
  1523.          */
  1524.     qfp = fopen(qf, "r+");
  1525. #else
  1526. a727 1
  1527. #endif /* hpux */
  1528. @
  1529.  
  1530.  
  1531. 5.30.0.4
  1532. log
  1533. @Dropped re-write of queue file due to bug w. too many open files.  This
  1534. isn't important to us and so will be dropped for now.
  1535.  
  1536. @
  1537. text
  1538. @d64 4
  1539. d77 1
  1540. a77 1
  1541. queueup(e, queueall, announce)
  1542. d81 1
  1543. d167 12
  1544. a178 2
  1545.         if (queueall ? !bitset(QDONTSEND, q->q_flags) :
  1546.                    bitset(QQUEUEUP, q->q_flags))
  1547. @
  1548.  
  1549.  
  1550. 5.30.0.5
  1551. log
  1552. @Bruce Lilly (bruce%balilly@@sonyd1.broadcast.sony.com) provided System 5
  1553. support, corrected several typos, and deleted extraneous newlines from
  1554. syslog() calls.  Re-did #statement indentation.  Made selection of
  1555. lockf() emulation of flock() more transparent: changed file open of
  1556. files to be exclusively locked from "r" (read-only) to "r+" (read/write);
  1557. added EAGAIN test to EWOULDBLOCK tests.  Fixed fencepost bug in third
  1558. expand() argument.
  1559. @
  1560. text
  1561. @d21 1
  1562. a21 2
  1563. #include <signal.h>
  1564. #include "sendmail.h"
  1565. d24 1
  1566. a24 1
  1567. # ifdef QUEUE
  1568. d26 1
  1569. a26 1
  1570. # else /* !QUEUE */
  1571. d28 1
  1572. a28 1
  1573. # endif /* QUEUE */
  1574. d31 1
  1575. a31 2
  1576. #include <sys/stat.h>
  1577. #ifndef SYSTEM5
  1578. d33 4
  1579. a36 7
  1580. #endif /* !SYSTEM5 */
  1581. #include <sys/file.h>
  1582. #ifndef LOCK_EX
  1583. # include "flock.h"
  1584. #endif /* !LOCK_EX */
  1585. #include <errno.h>
  1586. #include <pwd.h>
  1587. d38 1
  1588. a38 1
  1589. #ifdef QUEUE
  1590. d101 1
  1591. a101 1
  1592.                 if (errno != EWOULDBLOCK && errno != EAGAIN)
  1593. a103 2
  1594.                 unlink(tf);
  1595.                 sleep(1);
  1596. d109 1
  1597. a109 2
  1598.     if ((tfp = fdopen(fd, "w")) == NULL)
  1599.         syserr("cannot fdopen(%s)", tf);
  1600. d131 1
  1601. a131 2
  1602.         if ((dfp = fdopen(fd, "w")) == NULL)
  1603.             syserr("cannot fdopen(%s)", e->e_df);
  1604. d245 1
  1605. a245 1
  1606.             (void) expand(h->h_value, buf, &buf[(sizeof(buf)-1)], e);
  1607. d269 1
  1608. a269 1
  1609.         syslog(LOG_DEBUG, "%s: queueup, qf=%s, df=%s", e->e_id, qf, e->e_df);
  1610. d328 1
  1611. a328 1
  1612. # ifndef SIGCHLD
  1613. d330 1
  1614. a330 1
  1615. # else /* SIGCHLD */
  1616. d332 1
  1617. a332 1
  1618. # endif /* !SIGCHLD */
  1619. d338 1
  1620. a338 1
  1621. # ifndef SIGCHLD
  1622. d341 1
  1623. a341 1
  1624. # else /* SIGCHLD */
  1625. d343 1
  1626. a343 1
  1627. # endif /* !SIGCHLD */
  1628. d460 1
  1629. a460 1
  1630.             /* this may be some random person sending their msgs */
  1631. d712 1
  1632. d714 2
  1633. a715 2
  1634.          * We can't get an exclusive lock on a file that isn't opened for
  1635.      * writing on most systems - sigh!
  1636. d718 3
  1637. d968 1
  1638. a968 1
  1639. #endif /* QUEUE */
  1640. d1050 1
  1641. a1050 1
  1642. #ifdef LOG
  1643. d1053 1
  1644. a1053 1
  1645. #endif /* LOG */
  1646. d1080 1
  1647. a1080 1
  1648. #ifdef LOG
  1649. d1083 1
  1650. a1083 1
  1651. #endif /* LOG */
  1652. @
  1653.  
  1654.  
  1655. 5.30.0.6
  1656. log
  1657. @Save the values of the '$r' and '$s' macros in the queueing file.  Since
  1658. some parts of the parsing depend on these (and have since IDA-1.2.x),
  1659. this just makes the rewrite rules more consistent between items that are
  1660. immediately deliverable and items that must be queued for later.  I made
  1661. the character that marks the queueing record part of the '#define' so it can
  1662. be changed if some future changes from Berkeley should ever cause a conflict.
  1663.  
  1664. Neil Rickert (rickert@@cs.niu.edu)
  1665. @
  1666. text
  1667. @a265 14
  1668. #ifdef QUEUE_MACVALUE /* Save some macro values in the queue file */
  1669.     {
  1670.         char *p, *q;
  1671.         extern char *macvalue();
  1672.  
  1673.         for (p = "rs"; *p; p++)
  1674.         {
  1675.             q = macvalue(*p, CurEnv);
  1676.             if (q != NULL && *q)
  1677.                 fprintf(tfp, "%c%c%s\n", QUEUE_MACVALUE, *p, q);
  1678.         }
  1679.     }
  1680. #endif /* QUEUE_MACVALUE */
  1681.  
  1682. a798 6
  1683.  
  1684. #ifdef QUEUE_MACVALUE /* if macro values saved in queue file, restore them */
  1685.           case QUEUE_MACVALUE:
  1686.             setoption('M', &buf[1], FALSE, TRUE);
  1687.             break;
  1688. #endif /* QUEUE_MACVALUE */
  1689. @
  1690.  
  1691.  
  1692. 5.30.0.7
  1693. log
  1694. @Changed #ifdef SYSTEM5 to SYSV to be consistent with current usage.  Moved
  1695. #include <sys/file.h> to sendmail.h .
  1696. @
  1697. text
  1698. @d33 1
  1699. a33 1
  1700. #ifndef SYSV
  1701. d35 5
  1702. a39 1
  1703. #endif /* !SYSV */
  1704. @
  1705.  
  1706.  
  1707. 5.30.0.8
  1708. log
  1709. @Add calls to unlink tempfile before queueup() gives up and returns NULL.
  1710. Added syserr() and sleep() to do loop for case when tempfile exists.  If
  1711. an old tempfile somehow is there, the loop will spin very fast otherwise
  1712. w.o. saying why.  
  1713. @
  1714. text
  1715. @a99 5
  1716.             else {
  1717.                 syserr("queueup: temp file %s exists, sleeping",
  1718.                     tf);
  1719.                 sleep(30);
  1720.             }
  1721. d105 2
  1722. a107 1
  1723.                 sleep(1);
  1724. a132 1
  1725.             (void) unlink(tf);
  1726. @
  1727.  
  1728.  
  1729. 5.30.0.9
  1730. log
  1731. @Commented out tokens following #endif's.
  1732. @
  1733. text
  1734. @d267 1
  1735. a267 1
  1736. # ifdef QUEUE_MACVALUE /* Save some macro values in the queue file */
  1737. d279 1
  1738. a279 1
  1739. # endif /* QUEUE_MACVALUE */
  1740. d754 1
  1741. a754 1
  1742. # endif /* LOG */
  1743. d815 1
  1744. a815 1
  1745. # ifdef QUEUE_MACVALUE /* if macro values saved in queue file, restore them */
  1746. d819 1
  1747. a819 1
  1748. # endif /* QUEUE_MACVALUE */
  1749. @
  1750.  
  1751.  
  1752. 5.30.0.10
  1753. log
  1754. @Declare reapchild() to be SIG_TYPE.
  1755. @
  1756. text
  1757. @d349 1
  1758. a349 1
  1759.             extern SIG_TYPE reapchild();
  1760. @
  1761.  
  1762.  
  1763. 5.30.0.11
  1764. log
  1765. @sys/dir.h now included if direct is not defined rather than SYSV.
  1766. @
  1767. text
  1768. @d33 1
  1769. a33 1
  1770. #ifndef direct
  1771. d35 1
  1772. a35 1
  1773. #endif /* !direct */
  1774. @
  1775.  
  1776.  
  1777. 5.30.0.12
  1778. log
  1779. @Deleted #include <sys/types.h> as it's already included via sendmail.h from
  1780. useful.h.  #include "sendmail.h" relocated to top of #include list.
  1781. @
  1782. text
  1783. @d21 1
  1784. a22 1
  1785. #include <signal.h>
  1786. @
  1787.  
  1788.  
  1789. 5.30.0.13
  1790. log
  1791. @Added fsync() calls before close of df and cf files.  Helps prevent lost
  1792. mail on a system that's crashing often.  Depending on performance lossage
  1793. and portability constraints, this may need #ifdef PARANOID later.
  1794. @
  1795. text
  1796. @a142 2
  1797.         (void) fflush(dfp);
  1798.         (void) fsync(fileno(dfp));
  1799. a518 2
  1800.         (void) fflush(cf);
  1801.         (void) fsync(fileno(cf));
  1802. @
  1803.  
  1804.  
  1805. 5.30.0.14
  1806. log
  1807. @Added static keyword to declaration for getctluser(), orderq(), dowork(),
  1808. workcmpf(), readqf(), clrctluser(), setctluser().
  1809. @
  1810. text
  1811. @d177 1
  1812. a177 2
  1813.             char *ctluser;
  1814.             static char *getctluser();
  1815. d203 1
  1816. a203 2
  1817.             char *ctluser;
  1818.             static char *getctluser();
  1819. a321 1
  1820.     static orderq(), dowork();
  1821. a436 1
  1822. static
  1823. d446 1
  1824. a446 1
  1825.     static workcmpf();
  1826. a579 1
  1827. static
  1828. a606 1
  1829. static
  1830. d647 1
  1831. a647 2
  1832.         FILE *qflock;
  1833.         static FILE *readqf();
  1834. d722 1
  1835. a722 1
  1836. static FILE *
  1837. a732 1
  1838.     static clrctluser(), setctluser();
  1839. d1136 1
  1840. a1136 1
  1841. static char *
  1842. a1190 1
  1843. static
  1844. a1197 1
  1845. static
  1846. @
  1847.  
  1848.  
  1849. 5.30.0.15
  1850. log
  1851. @ANSIfied.
  1852. @
  1853. text
  1854. @a38 9
  1855. #ifdef __STDC__
  1856. static char * getctluser(ADDRESS *);
  1857. static void setctluser(const char *);
  1858. #else /* !__STDC__ */
  1859. static char * getctluser();
  1860. static void setctluser();
  1861. #endif /* __STDC__ */
  1862. static void clrctluser();
  1863.  
  1864. a56 12
  1865.  
  1866. # ifdef __STDC__
  1867. static orderq(int);
  1868. static workcmpf(const WORK *, const WORK *);
  1869. static void dowork(WORK *);
  1870. static FILE * readqf(ENVELOPE *, int);
  1871. # else /* !__STDC__ */
  1872. static orderq();
  1873. static workcmpf();
  1874. static void dowork();
  1875. static FILE * readqf();
  1876. # endif /* __STDC__ */
  1877. d103 1
  1878. a103 1
  1879.                 Xsleep(30);
  1880. d111 1
  1881. a111 1
  1882.                 Xsleep(1);
  1883. d129 1
  1884. d178 1
  1885. d205 1
  1886. d231 2
  1887. d274 1
  1888. a319 1
  1889. void
  1890. d323 3
  1891. a351 2
  1892.         if (pid > 0 && tTd(4, 2))
  1893.             printf("runqueue: forking (pid = %d)\n", pid);
  1894. d354 2
  1895. d450 1
  1896. d510 2
  1897. d586 2
  1898. a587 2
  1899.     register const WORK *a;
  1900.     register const WORK *b;
  1901. d612 1
  1902. a612 1
  1903. static void
  1904. d617 1
  1905. a639 2
  1906.         if (i > 0 && tTd(4, 2))
  1907.             printf("dowork: forking (pid = %d)\n", i);
  1908. d654 1
  1909. a654 1
  1910.  
  1911. d737 2
  1912. d740 1
  1913. a886 1
  1914. void
  1915. d927 1
  1916. a1113 1
  1917. void
  1918. d1148 1
  1919. d1199 1
  1920. a1199 1
  1921. static void
  1922. d1201 1
  1923. a1201 1
  1924.     register const char *str;
  1925. d1207 1
  1926. a1207 1
  1927. static void
  1928. a1230 1
  1929. void
  1930. @
  1931.  
  1932.  
  1933. 5.30.0.16
  1934. log
  1935. @Put overly long headers (> 500 bytes) at end of message body.  Adapted
  1936. from Paul Vixie's patch.
  1937. @
  1938. text
  1939. @d700 1
  1940. a700 1
  1941.         eatheader(CurEnv, NULL);
  1942. @
  1943.  
  1944.  
  1945. 5.30.0.17
  1946. log
  1947. @Record mailer used in logdelivery() routine.  From Stephen Cliffe
  1948. <steve@@cs.uow.edu.au>
  1949. @
  1950. text
  1951. @d207 1
  1952. a207 1
  1953.                     logdelivery(NULL, "queued");
  1954. @
  1955.  
  1956.  
  1957. 5.30.0.18
  1958. log
  1959. @Include signal.h from /usr/include/sys.  Supply work-around for rename()
  1960. (missing on SYSV).
  1961. @
  1962. text
  1963. @d22 1
  1964. a22 1
  1965. #include <sys/signal.h>
  1966. a304 6
  1967. # ifdef SYSV
  1968.     (void) unlink(qf);
  1969.     if (link(tf, qf) < 0)
  1970.         syserr("cannot rename(%s, %s), df=%s", tf, qf, e->e_df);
  1971.     (void) unlink(tf);
  1972. # else /* !SYSV */
  1973. a306 1
  1974. # endif /* SYSV */
  1975. @
  1976.  
  1977.  
  1978. 5.30.0.19
  1979. log
  1980. @Added RCS ID string
  1981. @
  1982. text
  1983. @a26 1
  1984. static char  rcsid[] = "@@(#)$Id$ (with queueing)";
  1985. a28 1
  1986. static char  rcsid[] = "@@(#)$Id$ (without queueing)";
  1987. @
  1988.  
  1989.  
  1990. 5.30.0.20
  1991. log
  1992. @Added new relatives of -q command line flag:  -Sfoo runs only those
  1993. queued messages with "foo" in the sender string, -Rfoo runs only those
  1994. that have foo in the recipient string, and -MAA07305 runs only the
  1995. message with the ID AA07305.  From patches adapted from Peter J Nilsson
  1996. (pjn@@ida.liu.se).
  1997. @
  1998. text
  1999. @d27 1
  2000. a27 1
  2001. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.19 1991/04/05 14:55:15 paul Exp paul $ (with queueing)";
  2002. d30 1
  2003. a30 1
  2004. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.19 1991/04/05 14:55:15 paul Exp paul $ (without queueing)";
  2005. d117 2
  2006. a118 4
  2007.         if (fd < 0)
  2008.         {
  2009.             if ( errno != EEXIST)
  2010.             {
  2011. d123 1
  2012. a123 2
  2013.             else
  2014.             {
  2015. d128 2
  2016. a129 5
  2017.         }
  2018.         else
  2019.         {
  2020.             if (flock(fd, LOCK_EX|LOCK_NB) < 0)
  2021.             {
  2022. a460 1
  2023. # define NEED_M        004
  2024. a471 1
  2025.     extern char *MatchRecipient, *MatchSender, *QueueID;
  2026. a528 3
  2027.         if (MatchRecipient || MatchSender || QueueID)
  2028.             i |= NEED_M;
  2029.  
  2030. a541 39
  2031.  
  2032.               case 'D':
  2033.                 /* We are running a certain queued message  */
  2034.                 if (QueueID && ((QueueID[0] == 'A' &&
  2035.                     !strncmp(&lbuf[3], QueueID, 7)) ||
  2036.                     (!strncmp(&lbuf[5], QueueID, 5))))
  2037.                     i &= ~NEED_M;
  2038.                 break;
  2039.  
  2040.               case 'R':
  2041.               case 'S':
  2042.               {
  2043.                 int    k, matchlen, recplen;
  2044.                 char    *mr;
  2045.  
  2046.                 /*
  2047.                  * Trying to match something in the Sender or
  2048.                  * Recipient field.
  2049.                  */
  2050.                 mr = (*lbuf == 'R') ? MatchRecipient
  2051.                             : MatchSender;
  2052.                 if (mr && (i & NEED_M))
  2053.                 {
  2054.                     matchlen = strlen(mr);
  2055.                     recplen = strlen(&lbuf[1]);
  2056.                     for (k = 1; (recplen - matchlen) >= 0;
  2057.                          k++)
  2058.                     {
  2059.                         if (!strncasecmp(mr, &lbuf[k],
  2060.                             matchlen))
  2061.                         {
  2062.                             i &= ~NEED_M;
  2063.                             break;
  2064.                         }
  2065.                         recplen--;
  2066.                     }
  2067.                 }
  2068.                 break;
  2069.               }
  2070. d544 2
  2071. d548 1
  2072. a548 1
  2073.         if (!doall && (shouldqueue(w->w_pri) || i == NEED_M))
  2074. d765 2
  2075. a766 2
  2076.     /*
  2077.      * We can't get an exclusive lock on a file that isn't opened for
  2078. d768 1
  2079. a768 1
  2080.      */
  2081. d992 1
  2082. a992 2
  2083.                 if (cbuf[0] != '\0')
  2084.                 {
  2085. d1084 2
  2086. a1085 4
  2087.             if (i < 0)
  2088.             {
  2089.                 if (errno != EEXIST)
  2090.                 {
  2091. d1090 1
  2092. a1090 3
  2093.             }
  2094.             else
  2095.             {
  2096. @
  2097.  
  2098.  
  2099. 5.30.0.21
  2100. log
  2101. @Relocated code to write macro values before addresses in queue file.
  2102. System 5 and general improvement patches contributed by Bruce Lilly
  2103. (bruce%balilly@@broadcast.sony.com).
  2104. @
  2105. text
  2106. @d26 2
  2107. a27 2
  2108. static char sccsid[] = "@@(#)queue.c    5.30 (Berkeley) 6/1/90 (with queueing)    %I% local";
  2109. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.20 1991/04/11 15:11:47 paul Exp paul $ (with queueing)";
  2110. d29 2
  2111. a30 2
  2112. static char sccsid[] = "@@(#)queue.c    5.30 (Berkeley) 6/1/90 (without queueing)    %I% local";
  2113. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.20 1991/04/11 15:11:47 paul Exp paul $ (without queueing)";
  2114. d70 2
  2115. a71 2
  2116. static int orderq(int);
  2117. static int workcmpf(const WORK *, const WORK *);
  2118. d75 2
  2119. a76 2
  2120. static int orderq();
  2121. static int workcmpf();
  2122. d108 1
  2123. a108 1
  2124.     int fd;
  2125. d147 1
  2126. a159 3
  2127. #ifdef SYSV
  2128.         fd = open(e->e_df, O_WRONLY|O_CREAT|O_SYNC, FileMode);
  2129. #else /* !SYSV */
  2130. a160 1
  2131. #endif /* SYSV */
  2132. a169 1
  2133.  
  2134. a171 1
  2135. #ifndef SYSV
  2136. a172 1
  2137. #endif /* !SYSV */
  2138. a195 13
  2139. # ifdef QUEUE_MACVALUE /* Save some macro values in the queue file */
  2140.     {
  2141.         char *p, *q;
  2142.  
  2143.         for (p = "rs"; *p; p++)
  2144.         {
  2145.             q = macvalue(*p, CurEnv);
  2146.             if (q != NULL && *q)
  2147.                 fprintf(tfp, "%c%c%s\n", QUEUE_MACVALUE, *p, q);
  2148.         }
  2149.     }
  2150. # endif /* QUEUE_MACVALUE */
  2151.  
  2152. d295 13
  2153. d469 1
  2154. a469 1
  2155. static int
  2156. d651 1
  2157. a651 1
  2158. static int
  2159. d806 1
  2160. @
  2161.  
  2162.  
  2163. 5.30.0.22
  2164. log
  2165. @For Received: headers (and others w.o. H_RCPT and H_FROM), reset $s
  2166. temporarily to DeclHostName.  DeclHostname contains the real host name
  2167. of the sender unless the name offered in the SMTP HELO command differs
  2168. from it.  It will then have the format "given (real)".
  2169. @
  2170. text
  2171. @d27 1
  2172. a27 1
  2173. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.21 1991/05/18 17:37:59 paul Exp paul $ (with queueing)";
  2174. d30 1
  2175. a30 1
  2176. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.21 1991/05/18 17:37:59 paul Exp paul $ (without queueing)";
  2177. a108 1
  2178.     char *macSvalue = macvalue('s', e);
  2179. a301 7
  2180.             /*
  2181.              * Use DeclHostName in headers that aren't H_RCPT
  2182.              * or H_FROM.  Restore the original value after the
  2183.              * expand().
  2184.              */
  2185.             if (!bitset(H_RCPT|H_FROM, h->h_flags) && DeclHostName)
  2186.                 define('s', DeclHostName, e);
  2187. a303 2
  2188.             if (!bitset(H_RCPT|H_FROM, h->h_flags) && DeclHostName)
  2189.                 define('s', macSvalue, e);
  2190. @
  2191.  
  2192.  
  2193. 5.30.0.23
  2194. log
  2195. @fsync() now done only if SuperSafe is set.
  2196. @
  2197. text
  2198. @d27 1
  2199. a27 1
  2200. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.22 1991/05/20 19:24:12 paul Exp paul $ (with queueing)";
  2201. d30 1
  2202. a30 1
  2203. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.22 1991/05/20 19:24:12 paul Exp paul $ (without queueing)";
  2204. d161 3
  2205. a163 3
  2206.         if (SuperSafe)
  2207.             fd = open(e->e_df, O_WRONLY|O_CREAT|O_SYNC, FileMode);
  2208.         else
  2209. a164 1
  2210.         fd = open(e->e_df, O_WRONLY|O_CREAT, FileMode);
  2211. d178 1
  2212. a178 2
  2213.         if (SuperSafe)
  2214.             (void) fsync(fileno(dfp));
  2215. @
  2216.  
  2217.  
  2218. 5.30.0.24
  2219. log
  2220. @Further changes for Interactive Systems UNIX adapted from patches
  2221. sent by Andy Linton <Andy.Linton@@comp.vuw.ac.nz>.
  2222. @
  2223. text
  2224. @d22 1
  2225. d27 1
  2226. a27 1
  2227. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.23 1991/05/20 22:31:10 paul Exp paul $ (with queueing)";
  2228. d30 1
  2229. a30 1
  2230. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.23 1991/05/20 22:31:10 paul Exp paul $ (without queueing)";
  2231. a38 3
  2232. #ifdef ISC
  2233. # include <net/errno.h>
  2234. #endif /* ISC */
  2235. @
  2236.  
  2237.  
  2238. 5.30.0.25
  2239. log
  2240. @First pass at adding Bruce Lilly's database auto-build code.
  2241. @
  2242. text
  2243. @d26 1
  2244. a26 1
  2245. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.24 1991/05/23 21:39:58 paul Exp paul $ (with queueing)";
  2246. d29 1
  2247. a29 1
  2248. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.24 1991/05/23 21:39:58 paul Exp paul $ (without queueing)";
  2249. a437 1
  2250. #if !defined(DBM_AUTOBUILD) || ( !defined(NDBM) && !defined(OTHERDBM) )
  2251. a442 1
  2252. #endif /* !DBM_AUTOBUILD || (!NDBM && !OTHERDBM) */
  2253. @
  2254.  
  2255.  
  2256. 5.30.0.26
  2257. log
  2258. @De-linting (omitted voids).
  2259. @
  2260. text
  2261. @d26 1
  2262. a26 1
  2263. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.25 1991/05/24 22:35:24 paul Exp paul $ (with queueing)";
  2264. d29 1
  2265. a29 1
  2266. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.25 1991/05/24 22:35:24 paul Exp paul $ (without queueing)";
  2267. d118 1
  2268. a118 1
  2269.         (void) strcpy(tf, queuename(e, 't'));
  2270. d349 1
  2271. a349 1
  2272.     (void) fflush(tfp);
  2273. d790 1
  2274. a790 1
  2275.         (void) fclose(qflock);
  2276. @
  2277.  
  2278.  
  2279. 5.30.0.27
  2280. log
  2281. @From: e07@@nikhefh.nikhef.nl (Eric Wassenaar)
  2282. Newsgroups: comp.mail.sendmail
  2283. Subject: sendmail may fetch values from wrong envelope
  2284. Date: 6 Jun 91 13:25:26 GMT
  2285. Organization: Nikhef-H, Amsterdam (the Netherlands).
  2286.  
  2287. To those who care about details:
  2288. In the following cases values may be fetched from the wrong
  2289. envelope, if the specified 'e' is not the same as 'CurEnv'.
  2290.  
  2291. Also:
  2292.  
  2293. To: "Mark D. Baushke" <mdb@@esd.3com.com>
  2294. Cc: Paul-Pomes@@uiuc.edu
  2295. Subject: Privacy concerns with $m
  2296. Date: Wed, 05 Jun 91 12:04:40 -0500
  2297. From: Neil Rickert <rickert@@cs.niu.edu>
  2298.  
  2299. What I had thought of using, instead of the complete recipient list,
  2300. was the following:
  2301.  
  2302. For each recipient on a single transaction, find the original
  2303. address (before aliasing, munging, etc) from which this was
  2304. derived.  If all recipients for the current transaction derive
  2305. from a single original recipient, use that for $m.  Else make
  2306. $m undefined.
  2307.  
  2308. This errs in the direction of privacy - you never see a Bcc:
  2309. recipient other than yourself, for example.  With multiple
  2310. local bcc: recipients, this means $m would be null, since
  2311. they are delivered to /bin/mail in one transaction.
  2312.  
  2313. Nevertheless, mail to a mailing list would normally show the
  2314. originating mailing list address before aliasing, etc.
  2315. @
  2316. text
  2317. @d26 1
  2318. a26 1
  2319. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.26 1991/06/01 22:18:25 paul Exp paul $ (with queueing)";
  2320. d29 1
  2321. a29 1
  2322. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.26 1991/06/01 22:18:25 paul Exp paul $ (without queueing)";
  2323. a111 1
  2324.     char *OrigUser = NULL;        /* Alias user list expanded from */
  2325. d213 1
  2326. a213 1
  2327.             q = macvalue(*p, e);
  2328. a246 12
  2329.             if (OrigUser != MACNULL)
  2330.             {
  2331.                 register ADDRESS *qq;
  2332.  
  2333.                 qq = q;
  2334.                 while (qq->q_alias != NULL)
  2335.                     qq = qq->q_alias;
  2336.                 if (OrigUser != NULL && OrigUser != qq->q_paddr)
  2337.                     OrigUser = MACNULL;
  2338.                 else
  2339.                     OrigUser = qq->q_paddr;
  2340.             }
  2341. a278 1
  2342.     define('m', OrigUser, e);
  2343. @
  2344.  
  2345.  
  2346. 5.30.0.28
  2347. log
  2348. @System 5 file sync'ing now wrapped with O_SYNC instead of SYSV, systems
  2349. that lack the rename() call now have the replacement link()/unlink()
  2350. wrapped with LACK_RENAME,  time_t replaced with TIME_TYPE.
  2351. @
  2352. text
  2353. @d25 2
  2354. a26 2
  2355. static char sccsid[] = "@@(#)queue.c    5.30 (Berkeley) 6/1/90 (with queueing)";
  2356. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.27 1991/06/08 14:51:14 paul Exp paul $ (with queueing)";
  2357. d28 2
  2358. a29 2
  2359. static char sccsid[] = "@@(#)queue.c    5.30 (Berkeley) 6/1/90 (without queueing)";
  2360. static char  rcsid[] = "@@(#)$Id: queue.c,v 5.30.0.27 1991/06/08 14:51:14 paul Exp paul $ (without queueing)";
  2361. d62 1
  2362. a62 1
  2363.     TIME_TYPE    w_ctime;    /* creation time of message */
  2364. d163 1
  2365. a163 1
  2366. #if defined(O_SYNC)
  2367. d167 1
  2368. a167 1
  2369. #endif /* O_SYNC */
  2370. d181 1
  2371. a181 1
  2372. #if !defined(O_SYNC)
  2373. d184 1
  2374. a184 1
  2375. #endif /* !O_SYNC */
  2376. d347 1
  2377. a347 1
  2378. #ifdef LACK_RENAME
  2379. d350 1
  2380. a350 1
  2381.         syserr("cannot link(%s, %s), df=%s", tf, qf, e->e_df);
  2382. d352 1
  2383. a352 1
  2384. #else /* !LACK_RENAME */
  2385. d355 1
  2386. a355 1
  2387. #endif /* LACK_RENAME */
  2388. d645 1
  2389. a645 5
  2390.     qsort(wlist, (size_t) min(wn, QUEUESIZE), sizeof (WORK),
  2391. #  ifdef __GNUC__
  2392.         /* prevent bogus warnings */ (int (*)())
  2393. #  endif /* __GNUC__ */
  2394.         workcmpf);
  2395. d655 1
  2396. a655 1
  2397.         w = (WORK *) xalloc(sizeof (WORK));
  2398. d1025 1
  2399. a1025 1
  2400.         auto TIME_TYPE submittime = 0;
  2401. d1100 1
  2402. a1100 1
  2403.         if (submittime == (TIME_TYPE) 0)
  2404. @
  2405.